home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _3598A18C61A54EE988577D3D98363E6A < prev    next >
Encoding:
Text File  |  2002-06-19  |  51.0 KB  |  1,983 lines

  1. // Copyright (C) 2001-2002 Raven Software.
  2. //
  3. // cg_main.c -- initialization and primary entry point for cgame
  4.  
  5. #include "cg_local.h"
  6. #include "../ui/ui_shared.h"
  7.  
  8. // display context for new ui stuff
  9. displayContextDef_t cgDC;
  10.  
  11. #if !defined(CL_LIGHT_H_INC)
  12.     #include "cg_lights.h"
  13. #endif
  14.  
  15.  
  16. int forceModelModificationCount = -1;
  17.  
  18. void CG_Init        ( int serverMessageNum, int serverCommandSequence, int clientNum );
  19. void CG_InitItems    ( void );
  20. void CG_Shutdown    ( void );
  21.  
  22. void CG_CalcEntityLerpPositions( centity_t *cent );
  23.  
  24. static int    C_PointContents            (void);
  25. static void C_GetLerpOrigin            (void);
  26. static void C_GetLerpAngles            (void);
  27. static void C_GetModelScale            (void);
  28. static void C_Trace                    (void);
  29. static void C_CameraShake            (void);
  30.  
  31. /*
  32. ================
  33. vmMain
  34.  
  35. This is the only way control passes into the module.
  36. This must be the very first function compiled into the .q3vm file
  37. ================
  38. */
  39. int vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11  ) 
  40. {
  41.     switch ( command ) 
  42.     {
  43.         case CG_INIT:
  44.             CG_Init( arg0, arg1, arg2 );
  45.             return 0;
  46.  
  47.         case CG_SHUTDOWN:
  48.             CG_Shutdown();
  49.             return 0;
  50.  
  51.         case CG_CONSOLE_COMMAND:
  52.             return CG_ConsoleCommand();
  53.  
  54.         case CG_DRAW_ACTIVE_FRAME:
  55.             CG_DrawActiveFrame( arg0, arg1, arg2 );
  56.             return 0;
  57.  
  58.         case CG_CROSSHAIR_PLAYER:
  59.             return CG_CrosshairPlayer();
  60.         
  61.         case CG_LAST_ATTACKER:
  62.             return CG_LastAttacker();
  63.         
  64.         case CG_KEY_EVENT:
  65.             CG_KeyEvent(arg0, arg1);
  66.             return 0;
  67.  
  68.         case CG_MOUSE_EVENT:
  69.             cgDC.cursorx = cgs.cursorX;
  70.             cgDC.cursory = cgs.cursorY;
  71.             
  72.             CG_MouseEvent(arg0, arg1);
  73.             return 0;
  74.  
  75.         case CG_EVENT_HANDLING:
  76.             CG_EventHandling(arg0);
  77.             return 0;
  78.  
  79.         case CG_POINT_CONTENTS:
  80.             return C_PointContents();
  81.  
  82.         case CG_GET_LERP_ORIGIN:
  83.             C_GetLerpOrigin();
  84.             return 0;
  85.  
  86.         case CG_GET_LERP_ANGLES:
  87.             C_GetLerpAngles();
  88.             return 0;
  89.  
  90.         case CG_GET_MODEL_SCALE:
  91.             C_GetModelScale();
  92.             return 0;
  93.  
  94.         case CG_GET_GHOUL2:
  95.             return (int)CG_GetEntity (arg0)->ghoul2;
  96.  
  97.         case CG_GET_MODEL_LIST:
  98.             return (int)cgs.gameModels;
  99.  
  100.         case CG_CALC_LERP_POSITIONS:
  101.             CG_CalcEntityLerpPositions( CG_GetEntity ( arg0 ) );
  102.             return 0;
  103.  
  104.         case CG_TRACE:
  105.             C_Trace();
  106.             return 0;
  107.  
  108.         case CG_GET_ORIGIN:
  109.             VectorCopy( CG_GetEntity (arg0)->currentState.pos.trBase, (float *)arg1);
  110.             return 0;
  111.  
  112.         case CG_GET_ANGLES:
  113.             VectorCopy( CG_GetEntity (arg0)->currentState.apos.trBase, (float *)arg1);
  114.             return 0;
  115.  
  116.         case CG_GET_ORIGIN_TRAJECTORY:
  117.             return (int)&CG_GetEntity (arg0)->nextState.pos;
  118.  
  119.         case CG_GET_ANGLE_TRAJECTORY:
  120.             return (int)&CG_GetEntity (arg0)->nextState.apos;
  121.  
  122.         case CG_FX_CAMERASHAKE:
  123.             C_CameraShake();
  124.             return 0;
  125.  
  126.         case CG_MISC_ENT:
  127.             CG_MiscEnt();
  128.             return 0;
  129.  
  130.         case CG_MAP_CHANGE:
  131.             // this trap map be called more than once for a given map change, as the
  132.             // server is going to attempt to send out multiple broadcasts in hopes that
  133.             // the client will receive one of them
  134.             cg.mMapChange = qtrue;
  135.             trap_S_ClearLoopingSounds ( qtrue );
  136.             trap_S_StopAllSounds ( );
  137.             trap_UI_CloseAll ( );
  138.             return 0;
  139.  
  140.         case CG_VOICE_EVENT:
  141.             Com_Printf ( "voice:  event %d\n", arg0 );
  142.             switch ( arg0 )
  143.             {
  144.                 case VEV_TALKSTART:
  145.                     if ( arg1 != cg.predictedPlayerState.clientNum )
  146.                     {
  147.                         trap_S_StartLocalSound ( trap_S_RegisterSound ( "sound/radiostart.wav" ), CHAN_AUTO );
  148.                     }
  149.                     cgs.clientinfo[arg1].voice = qtrue;
  150.                     break;
  151.  
  152.                 case VEV_TALKSTOP:
  153.                     if ( arg1 != cg.predictedPlayerState.clientNum )
  154.                     {
  155.                         trap_S_StartLocalSound ( trap_S_RegisterSound ( "sound/radiostart.wav" ), CHAN_AUTO );
  156.                     }
  157.                     cgs.clientinfo[arg1].voice = qfalse;
  158.                     break;
  159.             }
  160.                     
  161.             return 0;
  162.  
  163.         default:
  164.             Com_Error( ERR_FATAL, "vmMain: unknown command %i", command );
  165.             break;
  166.     }
  167.  
  168.     return -1;
  169. }
  170.  
  171. static int C_PointContents(void)
  172. {
  173.     TCGPointContents    *data = (TCGPointContents *)cg.sharedBuffer;
  174.  
  175.     return CG_PointContents( data->mPoint, data->mPassEntityNum );
  176. }
  177.  
  178. static void C_GetLerpOrigin(void)
  179. {
  180.     TCGVectorData        *data = (TCGVectorData *)cg.sharedBuffer;
  181.  
  182.     VectorCopy( CG_GetEntity (data->mEntityNum)->lerpOrigin, data->mPoint);
  183. }
  184.  
  185. static void C_GetLerpAngles(void)
  186. {
  187.     TCGVectorData        *data = (TCGVectorData *)cg.sharedBuffer;
  188.  
  189.     VectorCopy(CG_GetEntity(data->mEntityNum)->lerpAngles, data->mPoint);
  190. }
  191.  
  192. static void C_GetModelScale(void)
  193. {
  194.     TCGVectorData        *data = (TCGVectorData *)cg.sharedBuffer;
  195.  
  196.     VectorCopy(CG_GetEntity(data->mEntityNum)->modelScale, data->mPoint);
  197. }
  198.  
  199. static void C_Trace(void)
  200. {
  201.     TCGTrace    *td = (TCGTrace *)cg.sharedBuffer;
  202.  
  203.     CG_Trace(&td->mResult, td->mStart, td->mMins, td->mMaxs, td->mEnd, td->mSkipNumber, td->mMask);
  204. }
  205.  
  206. static void C_CameraShake(void)
  207. {
  208.     TCGCameraShake    *data = (TCGCameraShake *)cg.sharedBuffer;
  209.  
  210.     CG_CameraShake ( data->mOrigin, data->mIntensity, data->mRadius, data->mTime );
  211. }
  212.  
  213. cg_t                cg;
  214. cgs_t                cgs;
  215. centity_t            cg_entities[MAX_GENTITIES];
  216. centity_t            *cg_permanents[MAX_GENTITIES];
  217. int                    cg_numpermanents = 0;
  218. weaponInfo_t        cg_weapons[MAX_WEAPONS];
  219. itemInfo_t            cg_items[MAX_ITEMS];
  220.  
  221. vmCvar_t    cg_centertime;
  222. vmCvar_t    cg_centerY;
  223. vmCvar_t    cg_runpitch;
  224. vmCvar_t    cg_runroll;
  225. vmCvar_t    cg_bobup;
  226. vmCvar_t    cg_bobpitch;
  227. vmCvar_t    cg_bobroll;
  228. vmCvar_t    cg_shadows;
  229. vmCvar_t    cg_drawTimer;
  230. vmCvar_t    cg_drawFPS;
  231. vmCvar_t    cg_drawSnapshot;
  232. vmCvar_t    cg_drawCrosshair;
  233. vmCvar_t    cg_drawCrosshairNames;
  234. vmCvar_t    cg_drawRadar;
  235. vmCvar_t    cg_drawTeamScores;
  236. vmCvar_t    cg_drawHUDIcons;
  237. vmCvar_t    cg_crosshairSize;
  238. vmCvar_t    cg_crosshairGrow;
  239. vmCvar_t    cg_crosshairX;
  240. vmCvar_t    cg_crosshairY;
  241. vmCvar_t    cg_crosshairRGBA;
  242. vmCvar_t    cg_crosshairFriendRGBA;
  243. vmCvar_t    cg_draw2D;
  244. vmCvar_t    cg_debugEvents;
  245. vmCvar_t    cg_errorDecay;
  246. vmCvar_t    cg_nopredict;
  247. vmCvar_t    cg_showmiss;
  248. vmCvar_t    cg_footsteps;
  249. vmCvar_t    cg_drawGun;
  250. vmCvar_t    cg_gun_x;
  251. vmCvar_t    cg_gun_y;
  252. vmCvar_t    cg_gun_z;
  253. vmCvar_t    cg_autoswitch;
  254. vmCvar_t    cg_ignore;
  255. vmCvar_t    cg_simpleItems;
  256. vmCvar_t    cg_fov;
  257. vmCvar_t    cg_goreDetail;
  258. vmCvar_t    cg_thirdPerson;
  259. vmCvar_t    cg_thirdPersonRange;
  260. vmCvar_t    cg_thirdPersonYaw;
  261. vmCvar_t    cg_thirdPersonPitch;
  262. vmCvar_t    cg_thirdPersonHorzOffset;
  263. vmCvar_t    cg_stereoSeparation;
  264. vmCvar_t    cg_lagometer;
  265. vmCvar_t    cg_synchronousClients;
  266. vmCvar_t     cg_chatTime;
  267. vmCvar_t     cg_chatHeight;
  268. vmCvar_t     cg_stats;
  269. vmCvar_t     cg_buildScript;
  270. vmCvar_t     cg_forceModel;
  271. vmCvar_t    cg_paused;
  272. vmCvar_t    cg_predictItems;
  273. vmCvar_t    cg_antiLag;
  274. vmCvar_t    cg_impactPrediction;
  275. vmCvar_t    cg_autoReload;
  276. vmCvar_t    cg_deferPlayers;
  277. vmCvar_t    cg_drawFriend;
  278. vmCvar_t    cg_teamChatsOnly;
  279. vmCvar_t    cg_noVoiceText;
  280. vmCvar_t    cg_hudFiles;
  281. vmCvar_t     cg_smoothClients;
  282. vmCvar_t    pmove_fixed;
  283. vmCvar_t    pmove_msec;
  284. vmCvar_t    cg_pmove_msec;
  285. vmCvar_t    cg_cameraMode;
  286. vmCvar_t    cg_cameraOrbit;
  287. vmCvar_t    cg_cameraOrbitDelay;
  288. vmCvar_t    cg_timescale;
  289. vmCvar_t    cg_noProjectileTrail;
  290. vmCvar_t    cg_currentSelectedPlayer;
  291. vmCvar_t    cg_currentSelectedPlayerName;
  292. vmCvar_t    cg_DebugGore;
  293. vmCvar_t    cg_lockBlood;
  294. vmCvar_t    cg_lockSever;
  295. vmCvar_t    cg_lockDeaths;
  296. vmCvar_t    cg_marks;
  297. vmCvar_t    cg_shellEjection;
  298. vmCvar_t    RMG_distancecull;
  299.  
  300. vmCvar_t    cg_blueteamname;
  301. vmCvar_t    cg_redteamname;
  302.  
  303. vmCvar_t    cg_damageindicator;
  304. vmCvar_t    cg_tracerChance;
  305. vmCvar_t    cg_animBlend;
  306.  
  307. vmCvar_t    cg_automap_x;
  308. vmCvar_t    cg_automap_y;
  309. vmCvar_t    cg_automap_w;
  310. vmCvar_t    cg_automap_h;
  311. vmCvar_t    cg_automap_a;
  312.  
  313. vmCvar_t    ui_info_redcount;
  314. vmCvar_t    ui_info_bluecount;
  315. vmCvar_t    ui_info_speccount;
  316. vmCvar_t    ui_info_freecount;
  317. vmCvar_t    ui_info_pickupsdisabled;
  318. vmCvar_t    ui_info_seenobjectives;
  319.  
  320. vmCvar_t    cg_voiceRadio;
  321. vmCvar_t    cg_voiceGlobal;
  322. vmCvar_t    cg_soundGlobal;
  323. vmCvar_t    cg_soundFrag;
  324.  
  325. vmCvar_t    cg_weaponMenuFast;
  326.  
  327. vmCvar_t    cg_bodyTime;
  328.  
  329. vmCvar_t    cg_zoomWeaponChange;
  330.  
  331. vmCvar_t    rw_enabled;
  332.  
  333. typedef struct 
  334. {
  335.     vmCvar_t    *vmCvar;
  336.     char        *cvarName;
  337.     char        *defaultString;
  338.     int            cvarFlags;
  339.     float        mMinValue, mMaxValue;
  340. } cvarTable_t;
  341.  
  342. static cvarTable_t cvarTable[] = 
  343.     { &cg_lockBlood, "lock_blood", "1", 0 },
  344.     { &cg_lockSever, "lock_sever", "1", 0 },
  345.     { &cg_lockDeaths, "lock_deaths", "1", 0 },
  346.     { &rw_enabled,      "rw_enabled",    "0", 0 },
  347.  
  348.     { &cg_shellEjection, "cg_shellEjection", "1", CVAR_ARCHIVE },
  349.     { &cg_ignore, "cg_ignore", "0", 0 },
  350.     { &cg_autoswitch, "cg_autoswitch", "2", CVAR_ARCHIVE },
  351.     { &cg_drawGun, "cg_drawGun", "1", CVAR_ARCHIVE },
  352.     { &cg_fov, "cg_fov", "80", CVAR_ARCHIVE | CVAR_LOCK_RANGE, 80.0, 100.0 },
  353.     { &cg_stereoSeparation, "cg_stereoSeparation", "0.4", CVAR_ARCHIVE  },
  354.     { &cg_shadows, "cg_shadows", "1", CVAR_ARCHIVE  },
  355.     { &cg_draw2D, "cg_draw2D", "1", CVAR_ARCHIVE|CVAR_CHEAT  },
  356.     { &cg_drawTimer, "cg_drawTimer", "1", CVAR_ARCHIVE  },
  357.     { &cg_drawFPS, "cg_drawFPS", "0", CVAR_ARCHIVE  },
  358.     { &cg_drawSnapshot, "cg_drawSnapshot", "0", CVAR_ARCHIVE  },
  359.     { &cg_drawCrosshair, "cg_drawCrosshair", "4", CVAR_ARCHIVE },
  360.     { &cg_drawCrosshairNames, "cg_drawCrosshairNames", "1", CVAR_ARCHIVE },
  361.     { &cg_drawHUDIcons,    "cg_drawHUDIcons",    "1", CVAR_ARCHIVE },
  362.     { &cg_crosshairSize, "cg_crosshairSize", "24", CVAR_ARCHIVE },
  363.     { &cg_crosshairGrow, "cg_crosshairGrow", "1", CVAR_ARCHIVE },
  364.     { &cg_crosshairX, "cg_crosshairX", "0", CVAR_ARCHIVE },
  365.     { &cg_crosshairY, "cg_crosshairY", "0", CVAR_ARCHIVE },
  366.     { &cg_crosshairRGBA, "cg_crosshairRGBA", "1,1,1,1", CVAR_ARCHIVE },
  367.     { &cg_crosshairFriendRGBA, "cg_crosshairFriendRGBA", "1,0,0,1", CVAR_ARCHIVE },
  368.     { &cg_simpleItems, "cg_simpleItems", "0", CVAR_ARCHIVE },
  369.     { &cg_lagometer, "cg_lagometer", "0", CVAR_ARCHIVE },
  370.     { &cg_gun_x, "cg_gunX", "0", CVAR_CHEAT },
  371.     { &cg_gun_y, "cg_gunY", "0", CVAR_CHEAT },
  372.     { &cg_gun_z, "cg_gunZ", "0", CVAR_CHEAT },
  373.     { &cg_centertime, "cg_centertime", "4", CVAR_ARCHIVE },
  374.     { &cg_centerY,      "cg_centerY",  "70", CVAR_ARCHIVE },
  375.     { &cg_runpitch, "cg_runpitch", "0.002", CVAR_ARCHIVE|CVAR_LOCK_RANGE, 0.0f, 0.002f },
  376.     { &cg_runroll, "cg_runroll", "0.005", CVAR_ARCHIVE|CVAR_LOCK_RANGE, 0.0f, 0.005f },
  377.     { &cg_bobup , "cg_bobup", "0.005", CVAR_ARCHIVE|CVAR_LOCK_RANGE, 0.0f, 0.005f },
  378.     { &cg_bobpitch, "cg_bobpitch", "0.001", CVAR_ARCHIVE|CVAR_LOCK_RANGE, 0.0f, 0.001f },
  379.     { &cg_bobroll, "cg_bobroll", "0.001", CVAR_ARCHIVE|CVAR_LOCK_RANGE, 0.0f, 0.001f },
  380.     { &cg_debugEvents, "cg_debugevents", "0", CVAR_CHEAT },
  381.     { &cg_errorDecay, "cg_errordecay", "100", 0 },
  382.     { &cg_nopredict, "cg_nopredict", "0", 0 },
  383.     { &cg_showmiss, "cg_showmiss", "0", 0 },
  384.     { &cg_footsteps, "cg_footsteps", "1", CVAR_CHEAT },
  385.  
  386.     { &cg_goreDetail, "cg_goreDetail", "1", CVAR_ARCHIVE },
  387.  
  388.     { &cg_thirdPerson, "cg_thirdPerson", "0", CVAR_CHEAT },
  389.     { &cg_thirdPersonRange, "cg_thirdPersonRange", "80", CVAR_CHEAT },
  390.     { &cg_thirdPersonYaw, "cg_thirdPersonYaw", "0", CVAR_CHEAT },
  391.     { &cg_thirdPersonPitch, "cg_thirdPersonPitch", "15", CVAR_CHEAT },
  392.     
  393.     { &cg_thirdPersonHorzOffset, "cg_thirdPersonHorzOffset", "0", CVAR_CHEAT },
  394.  
  395.     { &cg_chatTime, "cg_chatTime", "8000", CVAR_ARCHIVE  },
  396.     { &cg_chatHeight, "cg_chatHeight", "4", CVAR_ARCHIVE  },
  397.     { &cg_forceModel, "cg_forceModel", "0", CVAR_ARCHIVE  },
  398.     { &cg_predictItems, "cg_predictItems", "1", CVAR_ARCHIVE },
  399.     { &cg_antiLag, "cg_antiLag", "1", CVAR_ARCHIVE | CVAR_USERINFO },
  400. #ifdef _SOF2_FLESHIMPACTPREDICTION
  401.     { &cg_impactPrediction, "cg_impactPrediction", "2", CVAR_ARCHIVE },
  402. #else
  403.     { &cg_impactPrediction, "cg_impactPrediction", "1", CVAR_ARCHIVE },
  404. #endif
  405.     { &cg_autoReload, "cg_autoReload", "1", CVAR_ARCHIVE | CVAR_USERINFO },
  406.     { &cg_deferPlayers, "cg_deferPlayers", "1", CVAR_ARCHIVE },
  407.     { &cg_stats, "cg_stats", "0", 0 },
  408.     { &cg_drawFriend, "cg_drawFriend", "1", CVAR_ARCHIVE },
  409.     { &cg_teamChatsOnly, "cg_teamChatsOnly", "0", CVAR_ARCHIVE },
  410.     { &cg_noVoiceText, "cg_noVoiceText", "0", CVAR_ARCHIVE },
  411.     // the following variables are created in other parts of the system,
  412.     // but we also reference them here
  413.     { &cg_buildScript, "com_buildScript", "0", 0 },    // force loading of all possible data amd error on failures
  414.     { &cg_paused, "cl_paused", "0", CVAR_ROM },
  415.     { &cg_synchronousClients, "g_synchronousClients", "0", 0 },    // communicated by systeminfo
  416.  
  417.     { &cg_currentSelectedPlayer, "cg_currentSelectedPlayer", "0", CVAR_ARCHIVE},
  418.     { &cg_currentSelectedPlayerName, "cg_currentSelectedPlayerName", "", CVAR_ARCHIVE},
  419.     { &cg_hudFiles, "cg_hudFiles", "ui/hud.txt", CVAR_ARCHIVE},
  420.  
  421.     { &cg_cameraOrbit, "cg_cameraOrbit", "0", CVAR_CHEAT},
  422.     { &cg_cameraOrbitDelay, "cg_cameraOrbitDelay", "50", CVAR_ARCHIVE},
  423.     { &cg_timescale, "timescale", "1", 0},
  424.     { &cg_smoothClients, "cg_smoothClients", "0", CVAR_USERINFO | CVAR_ARCHIVE},
  425.     { &cg_cameraMode, "com_cameraMode", "0", CVAR_CHEAT},
  426.  
  427.     { &pmove_fixed, "pmove_fixed", "0", 0},
  428.     { &pmove_msec, "pmove_msec", "8", 0},
  429.     { &cg_noProjectileTrail, "cg_noProjectileTrail", "0", CVAR_ARCHIVE},
  430.  
  431.     { &cg_DebugGore, "cg_debuggore", "", CVAR_CHEAT },
  432.     { &RMG_distancecull, "RMG_distancecull", "5000", CVAR_CHEAT },
  433.  
  434.     { &cg_blueteamname, "ui_blueteamname", "0", CVAR_ROM|CVAR_INTERNAL },
  435.     { &cg_redteamname, "ui_redteamname", "0", CVAR_ROM|CVAR_INTERNAL },
  436.  
  437.     { &cg_damageindicator, "cg_damageindicator", "1.5", CVAR_ARCHIVE },
  438.     { &cg_tracerChance,       "cg_tracerChance", "1", CVAR_ARCHIVE | CVAR_LOCK_RANGE, 0.0f, 0.50f },
  439.  
  440.     { &cg_animBlend, "cg_animBlend", "1", CVAR_ARCHIVE },
  441.  
  442.     { &cg_automap_x, "cg_automap_x", "485", CVAR_ARCHIVE | CVAR_LOCK_RANGE, 0.0, 629.0 },
  443.     { &cg_automap_y, "cg_automap_y", "5", CVAR_ARCHIVE  | CVAR_LOCK_RANGE, 0.0, 469.0},
  444.     { &cg_automap_w, "cg_automap_w", "150", CVAR_ARCHIVE | CVAR_LOCK_RANGE, 10.0, 640.0 },
  445.     { &cg_automap_h, "cg_automap_h", "150", CVAR_ARCHIVE | CVAR_LOCK_RANGE, 10.0, 480.0},
  446.     { &cg_automap_a, "cg_automap_a", "0.75", CVAR_ARCHIVE | CVAR_LOCK_RANGE, 0.0, 1.0},
  447.  
  448.     { &cg_drawRadar, "cg_drawRadar", "2", CVAR_ARCHIVE },
  449.     { &cg_drawTeamScores, "cg_drawTeamScores", "1", CVAR_ARCHIVE },
  450.  
  451.     { &ui_info_redcount, "ui_info_redcount", "0", CVAR_INTERNAL|CVAR_ROM },
  452.     { &ui_info_bluecount, "ui_info_bluecount", "0", CVAR_INTERNAL|CVAR_ROM },
  453.     { &ui_info_speccount, "ui_info_speccount", "0", CVAR_INTERNAL|CVAR_ROM },
  454.     { &ui_info_freecount, "ui_info_freecount", "0", CVAR_INTERNAL|CVAR_ROM },
  455.     { &ui_info_pickupsdisabled, "ui_info_pickupsdisabled", "0", CVAR_INTERNAL|CVAR_ROM },
  456.     { &ui_info_seenobjectives, "ui_info_seenobjectives", "0", CVAR_INTERNAL|CVAR_ROM },
  457.  
  458.     { &cg_voiceRadio,    "cg_voiceRadio",    "1",    CVAR_ARCHIVE,    0.0f,    0.0f },
  459.     { &cg_voiceGlobal,    "cg_voiceGlobal",    "1",    CVAR_ARCHIVE,    0.0f,    0.0f },
  460.     { &cg_soundGlobal,    "cg_soundGlobal",    "1",    CVAR_ARCHIVE,    0.0f,    0.0f },
  461.     { &cg_soundFrag,    "cg_soundFrag",        "1",    CVAR_ARCHIVE,    0.0f,    0.0f },
  462.     
  463.     { &cg_weaponMenuFast,  "cg_weaponMenuFast", "0", CVAR_ARCHIVE },
  464.  
  465.     { &cg_bodyTime,        "cg_bodyTime",            "0",    CVAR_ARCHIVE,    0.0f, 0.0f },
  466.  
  467.     { &cg_zoomWeaponChange,    "cg_zoomWeaponChange", "1", CVAR_ARCHIVE, 0.0f, 0.0f },
  468. };
  469.  
  470. static int  cvarTableSize = sizeof( cvarTable ) / sizeof( cvarTable[0] );
  471.  
  472. /*
  473. =================
  474. CG_RegisterCvars
  475. =================
  476. */
  477. void CG_RegisterCvars( void ) 
  478. {
  479.     int            i;
  480.     cvarTable_t    *cv;
  481.     char        var[MAX_TOKEN_CHARS];
  482.  
  483.     for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) 
  484.     {
  485.         trap_Cvar_Register( cv->vmCvar, cv->cvarName, cv->defaultString, cv->cvarFlags, cv->mMinValue, cv->mMaxValue );
  486.     }
  487.  
  488.     // see if we are also running the server on this machine
  489.     trap_Cvar_VariableStringBuffer( "sv_running", var, sizeof( var ) );
  490.     cgs.localServer = atoi( var );
  491.  
  492.     forceModelModificationCount = cg_forceModel.modificationCount;
  493.  
  494.     trap_Cvar_Register(NULL, "identity",        DEFAULT_IDENTITY, CVAR_USERINFO | CVAR_ARCHIVE, 0.0, 0.0 );
  495.     trap_Cvar_Register(NULL, "team_identity",    DEFAULT_IDENTITY, CVAR_USERINFO | CVAR_ARCHIVE, 0.0, 0.0 );
  496.     trap_Cvar_Register(NULL, "outfitting",        "AAAA",              CVAR_USERINFO | CVAR_ARCHIVE, 0.0, 0.0 );
  497.  
  498.     // Cvars uses for transferring data between client and server
  499.     trap_Cvar_Register(NULL, "ui_about_gametype",        "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  500.     trap_Cvar_Register(NULL, "ui_about_gametypename",    "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  501.     trap_Cvar_Register(NULL, "ui_about_scorelimit",        "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  502.     trap_Cvar_Register(NULL, "ui_about_timelimit",        "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  503.     trap_Cvar_Register(NULL, "ui_about_maxclients",        "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  504.     trap_Cvar_Register(NULL, "ui_about_dmflags",        "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  505.     trap_Cvar_Register(NULL, "ui_about_mapname",        "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  506.     trap_Cvar_Register(NULL, "ui_about_hostname",        "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  507.     trap_Cvar_Register(NULL, "ui_about_needpass",        "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  508.     trap_Cvar_Register(NULL, "ui_about_botminplayers",    "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  509.     trap_Cvar_Register(NULL, "ui_info_availableweapons","0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  510.  
  511.     trap_Cvar_Register(NULL, "ui_info_redscore",        "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  512.     trap_Cvar_Register(NULL, "ui_info_bluescore",        "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  513.  
  514.     trap_Cvar_Register(NULL, "cg_lastobjectives",        "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  515.  
  516.     trap_Cvar_Register(NULL, "ui_about_seed",            "0", CVAR_ROM|CVAR_INTERNAL, 0.0, 0.0 );
  517.  
  518.     trap_Cvar_Set ( "ui_info_seenobjectives", "0" );
  519.     trap_Cvar_Set ( "ui_info_redscore", "0" );
  520.     trap_Cvar_Set ( "ui_info_bluescore", "0" );
  521. }
  522.  
  523. /*                                                                                                                                            
  524. ===================
  525. CG_ForceModelChange
  526. ===================
  527. */
  528. static void CG_ForceModelChange( void ) 
  529. {
  530.     int        i;
  531.  
  532.     for (i=0 ; i<MAX_CLIENTS ; i++) 
  533.     {
  534.         const char        *clientInfo;
  535.  
  536.         clientInfo = CG_ConfigString( CS_PLAYERS+i );
  537.         if ( !clientInfo[0] ) 
  538.         {
  539.             continue;
  540.         }
  541.  
  542.         CG_NewClientInfo( i );
  543.     }
  544. }
  545.  
  546. /*
  547. ==================
  548. CG_UpdateTeamCountCvars
  549. ==================
  550. */
  551. void CG_UpdateTeamCountCvars ( void )
  552. {
  553.     int i;
  554.     int counts[TEAM_NUM_TEAMS];
  555.  
  556.     memset ( counts, 0, sizeof(counts) );
  557.  
  558.     for ( i = 0 ; i < cgs.maxclients ; i++ ) 
  559.     {
  560.         clientInfo_t* cl;
  561.         
  562.         cl = &cgs.clientinfo[ i ];
  563.  
  564.         if ( !cl->infoValid )
  565.         {
  566.             continue;
  567.         }
  568.         
  569.         counts[cl->team]++;
  570.     }
  571.  
  572.     trap_Cvar_Set ( "ui_info_redcount",  va("%i", counts[TEAM_RED] ) );
  573.     trap_Cvar_Set ( "ui_info_bluecount", va("%i", counts[TEAM_BLUE]) );
  574.     trap_Cvar_Set ( "ui_info_freecount", va("%i", counts[TEAM_FREE]) );
  575.     trap_Cvar_Set ( "ui_info_speccount", va("%i", counts[TEAM_SPECTATOR] ) );
  576. }
  577.  
  578. /*
  579. =================
  580. CG_UpdateCvars
  581. =================
  582. */
  583. void CG_UpdateCvars( void ) 
  584. {
  585.     int            i;
  586.     cvarTable_t    *cv;
  587.  
  588.     static int crosshairRGBAModificationCount = -1;
  589.     static int crosshairFriendRGBAModificationCount = -1;
  590.  
  591.     for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) 
  592.     {
  593.         trap_Cvar_Update( cv->vmCvar );
  594.     }
  595.  
  596.     // if force model changed
  597.     if ( forceModelModificationCount != cg_forceModel.modificationCount ) 
  598.     {
  599.         forceModelModificationCount = cg_forceModel.modificationCount;
  600.         CG_ForceModelChange();
  601.     }
  602.  
  603.     // If the crosshair RGBA was modified then update the globals
  604.     if ( crosshairRGBAModificationCount != cg_crosshairRGBA.modificationCount )
  605.     {
  606.         sscanf ( cg_crosshairRGBA.string, "%f,%f,%f,%f", 
  607.                  &cg.crosshairRGBA[0],
  608.                  &cg.crosshairRGBA[1],
  609.                  &cg.crosshairRGBA[2],
  610.                  &cg.crosshairRGBA[3] );
  611.  
  612.         crosshairRGBAModificationCount = cg_crosshairRGBA.modificationCount;
  613.     }
  614.  
  615.     // If the crosshair RGBA was modified then update the globals
  616.     if ( crosshairFriendRGBAModificationCount != cg_crosshairFriendRGBA.modificationCount )
  617.     {
  618.         sscanf ( cg_crosshairFriendRGBA.string, "%f,%f,%f,%f", 
  619.                  &cg.crosshairFriendRGBA[0],
  620.                  &cg.crosshairFriendRGBA[1],
  621.                  &cg.crosshairFriendRGBA[2],
  622.                  &cg.crosshairFriendRGBA[3] );
  623.  
  624.         crosshairFriendRGBAModificationCount = cg_crosshairFriendRGBA.modificationCount;
  625.     }
  626. }
  627.  
  628. int CG_CrosshairPlayer( void ) 
  629. {
  630.     if ( cg.time > ( cg.crosshairClientTime + 1000 ) ) 
  631.     {
  632.         return -1;
  633.     }
  634.     return cg.crosshairClientNum;
  635. }
  636.  
  637. int CG_LastAttacker( void ) {
  638.     if ( !cg.attackerTime ) {
  639.         return -1;
  640.     }
  641.     return cg.snap->ps.persistant[PERS_ATTACKER];
  642. }
  643.  
  644. #ifndef CGAME_HARD_LINKED
  645. // this is only here so the functions in q_shared.c and bg_*.c can link (FIXME)
  646.  
  647. void QDECL Com_Error( int level, const char *msg, ... ) 
  648. {
  649.     va_list        argptr;
  650.     char        text[1024];
  651.  
  652.     va_start (argptr, msg);
  653.     vsprintf (text, msg, argptr);
  654.     va_end (argptr);
  655.  
  656.     trap_Error( text );
  657. }
  658.  
  659. void QDECL Com_Printf( const char *msg, ... ) 
  660. {
  661.     va_list        argptr;
  662.     char        text[1024];
  663.  
  664.     va_start (argptr, msg);
  665.     vsprintf (text, msg, argptr);
  666.     va_end (argptr);
  667.  
  668.     trap_Print( text );
  669. }
  670.  
  671. #endif
  672.  
  673. /*
  674. =================
  675. CG_GetEntity
  676.  
  677. This function handles the predicted player entitiy specially.  The player
  678. should always be using the predicted entity rather than whats in the main 
  679. entity array.
  680. =================
  681. */
  682. centity_t* CG_GetEntity ( int index )
  683. {
  684. /*
  685.     if ( index == cg.clientNum )
  686.     {
  687.         return &cg.predictedPlayerEntity;
  688.     }
  689. */
  690.  
  691.     return &cg_entities[index];
  692. }
  693.  
  694. /*
  695. ================
  696. CG_Argv
  697. ================
  698. */
  699. const char *CG_Argv( int arg ) {
  700.     static char    buffer[MAX_STRING_CHARS];
  701.  
  702.     trap_Argv( arg, buffer, sizeof( buffer ) );
  703.  
  704.     return buffer;
  705. }
  706.  
  707.  
  708. //========================================================================
  709.  
  710. /*
  711. =================
  712. CG_RegisterItemSounds
  713.  
  714. The server says this item is used on this level
  715. =================
  716. */
  717. static void CG_RegisterItemSounds( int itemNum ) {
  718.     gitem_t            *item;
  719.     char            data[MAX_QPATH];
  720.     char            *s, *start;
  721.     int                len;
  722.  
  723.     item = &bg_itemlist[ itemNum ];
  724.  
  725.     if( item->pickup_sound ) {
  726.         trap_S_RegisterSound( item->pickup_sound );
  727.     }
  728.  
  729.     // parse the space seperated precache string for other media
  730.     s = item->sounds;
  731.     if (!s || !s[0])
  732.     {
  733.         return;
  734.     }
  735.  
  736.     while (*s) {
  737.         start = s;
  738.         while (*s && *s != ' ') 
  739.         {
  740.             s++;
  741.         }
  742.  
  743.         len = s-start;
  744.         if (len >= MAX_QPATH || len < 5) 
  745.         {
  746.             Com_Error( ERR_FATAL, "PrecacheItem: %s has bad precache string", item->classname);
  747.             return;
  748.         }
  749.         memcpy (data, start, len);
  750.         data[len] = 0;
  751.         if ( *s ) 
  752.         {
  753.             s++;
  754.         }
  755.  
  756.         if ( !strcmp(data+len-3, "wav" )) 
  757.         {
  758.             trap_S_RegisterSound( data );
  759.         }
  760.     }
  761. }
  762.  
  763. /*
  764. =================
  765. CG_RegisterLadders
  766.  
  767. Registers all the ladders in the current map
  768. =================
  769. */
  770. static void CG_RegisterLadders ( void )
  771. {
  772.     int            i;
  773.     const char    *ladder;
  774.  
  775.     for ( i = 0 ; i < MAX_LADDERS ; i++ ) 
  776.     {
  777.         vec3_t absmin;
  778.         vec3_t absmax;
  779.         vec3_t fwd;
  780.         vec3_t angles;
  781.  
  782.         ladder = CG_ConfigString( CS_LADDERS + i );
  783.         
  784.         // No ladder?    
  785.         if ( !ladder || !ladder[0] )
  786.         {
  787.             continue;
  788.         }
  789.  
  790.         VectorClear ( angles );
  791.         sscanf ( ladder, "%f,%f,%f,%f,%f,%f,%f",
  792.                  &absmin[0], &absmin[1], &absmin[2],
  793.                  &absmax[0], &absmax[1], &absmax[2],
  794.                  &angles[YAW] );
  795.  
  796.         AngleVectors( angles, fwd, 0, 0);
  797.  
  798.         BG_AddLadder ( absmin, absmax, fwd );
  799.     }
  800. }
  801.  
  802. /*
  803. =================
  804. CG_RegisterSounds
  805.  
  806. called during a precache command
  807. =================
  808. */
  809. static void CG_RegisterSounds( void ) 
  810. {
  811.     int        i;
  812.     char    items[MAX_ITEMS+1];
  813.     const char    *soundName;
  814.  
  815.     // voice commands
  816.     CG_LoadVoiceChats();
  817.  
  818.     CG_LoadingStage ( 3 );
  819.  
  820.     cgs.media.talkSound = trap_S_RegisterSound( "sound/player/talk.wav" );
  821.  
  822.     cgs.media.waterFootstep[0] = trap_S_RegisterSound( "sound/player/steps/water/water_step0");    
  823.     cgs.media.waterFootstep[1] = trap_S_RegisterSound( "sound/player/steps/water/water_step1");    
  824.  
  825.     cgs.media.waterWade[0] = trap_S_RegisterSound( "sound/player/steps/water/water_wade0");    
  826.     cgs.media.waterWade[1] = trap_S_RegisterSound( "sound/player/steps/water/water_wade1");    
  827.  
  828.     cgs.media.waterJumpIn    = trap_S_RegisterSound( "sound/player/jumps/water_jump");    
  829.     cgs.media.waterLeave    = trap_S_RegisterSound( "sound/pain_death/mullins/water_surface");    
  830.  
  831.     cgs.media.armorHitSound[0] = trap_S_RegisterSound( "sound/pain_death/mullins/armor01");    
  832.     cgs.media.armorHitSound[1] = trap_S_RegisterSound( "sound/pain_death/mullins/armor02");    
  833.     cgs.media.fleshHitSound[0] = trap_S_RegisterSound( "sound/pain_death/mullins/hit01");    
  834.     cgs.media.fleshHitSound[1] = trap_S_RegisterSound( "sound/pain_death/mullins/hit02");    
  835.  
  836.     // only register the items that the server says we need
  837.     strcpy( items, CG_ConfigString( CS_ITEMS ) );
  838.  
  839.     CG_LoadingStage ( 4 );
  840.  
  841.     for (i = 0; i < MAX_AMBIENT_SOUNDSETS; i++)    // 0 is reserved for current
  842.     {
  843.         const char *psString = CG_ConfigString( CS_AMBIENT_SOUNDSETS + i);            
  844.  
  845.         if (psString && strlen(psString))
  846.         {
  847.             trap_AS_AddPrecacheEntry( psString );
  848.         }
  849.         else
  850.         {
  851. //            break;    // EOL
  852.         }
  853.     }
  854.  
  855.     trap_AS_ParseSets();
  856.  
  857.     for ( i = 1 ; i < bg_numItems ; i++ ) 
  858.     {
  859.         CG_RegisterItemSounds( i );
  860.     }
  861.  
  862.     for ( i = 1 ; i < MAX_SOUNDS ; i++ ) 
  863.     {
  864.         soundName = CG_ConfigString( CS_SOUNDS+i );
  865.         
  866.         if ( !soundName[0] ) 
  867.         {
  868.             break;
  869.         }
  870.         
  871.         // custom sound
  872.         if ( soundName[0] == '*' ) 
  873.         {
  874.             continue;    
  875.         }
  876.  
  877.         cgs.gameSounds[i] = trap_S_RegisterSound( soundName );
  878.     }
  879.  
  880.  
  881.     cgs.media.glassBreakSound = trap_S_RegisterSound("sound/effects/glassbreak1.wav");
  882.  
  883.     // Respawn sound is only used in gametypes where you respawn
  884.     if ( cgs.gametypeData->respawnType != RT_NONE )
  885.     {
  886.         cgs.media.respawnSound = trap_S_RegisterSound("sound/player_respawn.wav");
  887.     }
  888.  
  889.     cgs.media.itemRespawnSound = trap_S_RegisterSound ( "sound/item_respawn.mp3" );
  890.  
  891.     cgs.media.fragSound       = trap_S_RegisterSound ( "sound/frag.mp3" );
  892.     cgs.media.fragSelfSound   = trap_S_RegisterSound ( "sound/self_frag.mp3" );
  893.     cgs.media.zoomSound       = trap_S_RegisterSound ( "sound/weapons/sniper/scope_zoom.wav" );
  894.     cgs.media.gogglesOnSound  = trap_S_RegisterSound ( "sound/weapons/goggles/turn_on.mp3" );
  895.     cgs.media.gogglesOffSound = trap_S_RegisterSound ( "sound/weapons/goggles/turn_off.mp3" );
  896.  
  897.     // Move out sound
  898.     if ( cgs.gametypeData->respawnType == RT_NONE )
  899.     {
  900.         cgs.media.goSound = trap_S_RegisterSound ( "sound/radio/male/move.mp3" );
  901.     }
  902.  
  903.     // bullet flyby sounds
  904.     for (i = 0; i < NUMFLYBYS; i++)
  905.     {
  906.         cgs.media.flybySounds[i] = trap_S_RegisterSound ( va("sound/player/bullet_impacts/whine/b_whine%d", i));
  907.     }
  908.  
  909.     // Water sounds
  910.     cgs.media.drownPainSound[0] = trap_S_RegisterSound ( "sound/pain_death/mullins/drown01.mp3" );
  911.     cgs.media.drownPainSound[1] = trap_S_RegisterSound ( "sound/pain_death/mullins/drown02.mp3" );
  912.     cgs.media.drownDeathSound   = trap_S_RegisterSound ( "sound/pain_death/mullins/drown_dead.mp3" );
  913.  
  914.     CG_LoadingStage ( 5 );
  915. }
  916.  
  917.  
  918. //-------------------------------------
  919. // CG_RegisterEffects
  920. // 
  921. // Handles precaching all effect files
  922. //    and any shader, model, or sound
  923. //    files an effect may use.
  924. //-------------------------------------
  925. static void CG_RegisterEffects( void )
  926. {
  927.     const char    *effectName;
  928.     int            i;
  929.  
  930.     for ( i = 1 ; i < MAX_FX ; i++ ) 
  931.     {
  932.         effectName = CG_ConfigString( CS_EFFECTS + i );
  933.  
  934.         if ( !effectName[0] ) 
  935.         {
  936.             break;
  937.         }
  938.  
  939.         trap_FX_RegisterEffect( effectName );
  940.     }
  941. }
  942.  
  943. //===================================================================================
  944.  
  945.  
  946. /*
  947. =================
  948. CG_RegisterGraphics
  949.  
  950. This function may execute for a couple of minutes with a slow disk.
  951. =================
  952. */
  953. static void CG_RegisterGraphics( void ) 
  954. {
  955.     int            i;
  956.     char        items[MAX_ITEMS+1];
  957.     int            sub;
  958.     char        temp[MAX_QPATH];
  959.     int            breakPoint;
  960.     const char    *terrainInfo;
  961.     int            terrainID;
  962.     vec3_t        distance;
  963.  
  964.     // clear any references to old media
  965.     memset( &cg.refdef, 0, sizeof( cg.refdef ) );
  966.     trap_R_ClearScene();
  967.  
  968.     // Load the map
  969.     CG_LoadingString( cgs.mapname );
  970.  
  971.     trap_R_LoadWorldMap( cgs.mapname );
  972.  
  973.     // precache status bar pics
  974.     CG_LoadingString( "game media" );
  975.  
  976.     CG_LoadingStage ( 6 );
  977.  
  978.     cgs.media.cursor = trap_R_RegisterShaderNoMip( "gfx/menus/cursor/cursor" );
  979.  
  980.     // Register the graphics for the scoreboard
  981.     cgs.media.scoreboard       = trap_R_RegisterShaderNoMip ( "gfx/menus/scoreboard/scoreboard.tga" );
  982.     cgs.media.scoreboardHeader = trap_R_RegisterShaderNoMip ( "gfx/menus/scoreboard/scorelineheader.tga" );
  983.     cgs.media.scoreboardLine   = trap_R_RegisterShaderNoMip ( "gfx/menus/scoreboard/scoreline.tga" );
  984.     cgs.media.scoreboardFooter = trap_R_RegisterShaderNoMip ( "gfx/menus/scoreboard/scorelinefooter.tga" );
  985.     cgs.media.scoreboardTotals = trap_R_RegisterShaderNoMip ( "gfx/menus/scoreboard/scorelinetotals.tga" );
  986.  
  987.     cgs.media.smokePuffShader = trap_R_RegisterShader( "smokePuff" );
  988.     cgs.media.lagometerShader = trap_R_RegisterShader("gfx/menus/hud/lagometer.tga" );
  989.     cgs.media.disconnectShader = trap_R_RegisterShader("gfx/menus/hud/disconnect.tga" );
  990.     cgs.media.waterBubbleShader = trap_R_RegisterShader( "gfx/misc/bubble" );
  991.     cgs.media.backTileShader = trap_R_RegisterShader( "gfx/2d/backtile" );
  992.  
  993.     cgs.media.mAutomapPlayerIcon = trap_R_RegisterShader( "gfx/menus/rmg/arrow_w" );
  994.  
  995.     CG_LoadingStage ( 7 );
  996.  
  997.     Com_Printf( S_COLOR_CYAN "---------- Fx System Initialization ---------\n" );
  998.     trap_FX_InitSystem( &cg.refdef);
  999.  
  1000.     Com_Printf( S_COLOR_CYAN "----- Fx System Initialization Complete -----\n" );
  1001.     CG_RegisterEffects();
  1002.  
  1003.     // Initialize the materials
  1004.     trap_MAT_Init();
  1005.  
  1006.     CG_LoadingStage ( 8 );
  1007.  
  1008.     // Initialize the crosshairs
  1009.     for ( i = 0 ; i < NUM_CROSSHAIRS ; i++ ) 
  1010.     {
  1011.         cgs.media.crosshairShader[i] = trap_R_RegisterShader( va("gfx/menus/crosshairs/ch%i", i) );
  1012.     }
  1013.  
  1014.     CG_LoadingStage ( 9 );
  1015.  
  1016.     if ( cgs.gametypeData->teams ) 
  1017.     {
  1018.         cgs.media.blueFriendShader = trap_R_RegisterShader ( "gfx/menus/hud/team_blue" );
  1019.         cgs.media.redFriendShader  = trap_R_RegisterShader ( "gfx/menus/hud/team_red" );
  1020.         cgs.media.radarShader       = trap_R_RegisterShaderNoMip ( "gfx/menus/hud/radar.png" );
  1021.     }
  1022.  
  1023.     cgs.media.botSmallShader = trap_R_RegisterShaderNoMip ( "gfx/menus/hud/bot_small" );
  1024.     cgs.media.armorShader     = trap_R_RegisterShaderNoMip ( "gfx/menus/hud/hud_armor" );
  1025.     cgs.media.deadShader     = trap_R_RegisterShaderNoMip ( "gfx/menus/hud/dead" );
  1026.  
  1027.     CG_LoadingStage ( 10 );
  1028.  
  1029.     // Initialize weapons, load them all 
  1030.     memset( cg_weapons, 0, sizeof( cg_weapons ) );
  1031.  
  1032.     for (i = WP_NONE + 1; i < WP_NUM_WEAPONS; i ++ )
  1033.     {
  1034.         if ( cgs.pickupsDisabled && !BG_IsWeaponAvailableForOutfitting ( i, 2 ) )
  1035.         {
  1036.             continue;
  1037.         }
  1038.  
  1039.         CG_RegisterWeapon ( i );
  1040.     }
  1041.  
  1042.     CG_LoadingStage ( 11 );
  1043.  
  1044.     // only register the items that the server says we need
  1045.     strcpy( items, CG_ConfigString( CS_ITEMS) );
  1046.  
  1047.     for ( i = 1 ; i < bg_numItems ; i++ ) 
  1048.     {
  1049.         // Dont bother with weapons, theyare already loaded
  1050.  
  1051.         if ( items[ i ] == '1' || cg_buildScript.integer ) 
  1052.         {
  1053.             CG_RegisterItemVisuals( i );
  1054.         }
  1055.     }
  1056.  
  1057.     CG_LoadingStage ( 12 );
  1058.  
  1059.     // wall marks
  1060.     cgs.media.burnMarkShader    = trap_R_RegisterShader( "gfx/damage/burnmark5" );
  1061.     cgs.media.shadowMarkShader    = trap_R_RegisterShader( "markShadow" );
  1062.     cgs.media.wakeMarkShader    = trap_R_RegisterShader( "wake" );
  1063.     cgs.media.bloodMarkShader    = trap_R_RegisterShader( "bloodMark" );
  1064.     cgs.media.mAutomap            = 0;
  1065.  
  1066.     // register the inline models
  1067.     breakPoint = cgs.numInlineModels = trap_CM_NumInlineModels();
  1068.     for ( i = 0 ; i < cgs.numInlineModels ; i++ ) 
  1069.     {
  1070.         char    name[10];
  1071.         vec3_t    mins;
  1072.         vec3_t    maxs;
  1073.         int        j;
  1074.  
  1075.         Com_sprintf( name, sizeof(name), "*%i", i );
  1076.         cgs.inlineDrawModel[i] = trap_R_RegisterModel( name );
  1077.         if (!cgs.inlineDrawModel[i])
  1078.         {
  1079.             breakPoint = i;
  1080.             break;
  1081.         }
  1082.  
  1083.         trap_R_ModelBounds( cgs.inlineDrawModel[i], mins, maxs );
  1084.         for ( j = 0 ; j < 3 ; j++ ) 
  1085.         {
  1086.             cgs.inlineModelMidpoints[i][j] = mins[j] + 0.5 * ( maxs[j] - mins[j] );
  1087.         }
  1088.     }
  1089.  
  1090.     // register all the server specified models
  1091.     for (i=1 ; i<MAX_MODELS ; i++) 
  1092.     {
  1093.         const char    *modelName;
  1094.  
  1095.         modelName = CG_ConfigString( CS_MODELS+i );
  1096.         if ( !modelName[0] ) 
  1097.         {
  1098.             break;
  1099.         }
  1100.         cgs.gameModels[i] = trap_R_RegisterModel( modelName );
  1101.     }
  1102.  
  1103.     // register all the server specified icons
  1104.     for ( i = 1; i < MAX_ICONS; i ++ )
  1105.     {
  1106.         const char* iconName;
  1107.  
  1108.         iconName = CG_ConfigString ( CS_ICONS + i );
  1109.         if ( !iconName[0] )
  1110.         {
  1111.             break;
  1112.         }
  1113.  
  1114.         cgs.gameIcons[i] = trap_R_RegisterShaderNoMip ( iconName );
  1115.     }
  1116.  
  1117.     CG_LoadingString( "BSP instances" );
  1118.  
  1119.     for(i = 1; i < MAX_SUB_BSP; i++)
  1120.     {
  1121.         const char        *bspName = 0;
  1122.         vec3_t            mins, maxs;
  1123.         int                j;
  1124.  
  1125.         bspName = CG_ConfigString( CS_BSP_MODELS+i );
  1126.         if ( !bspName[0] ) 
  1127.         {
  1128.             break;
  1129.         }
  1130.  
  1131.         trap_CM_LoadMap( bspName, qtrue );
  1132.         cgs.inlineDrawModel[breakPoint] = trap_R_RegisterModel( bspName );
  1133.         trap_R_ModelBounds( cgs.inlineDrawModel[breakPoint], mins, maxs );
  1134.         for ( j = 0 ; j < 3 ; j++ ) 
  1135.         {
  1136.             cgs.inlineModelMidpoints[breakPoint][j] = mins[j] + 0.5 * ( maxs[j] - mins[j] );
  1137.         }
  1138.         breakPoint++;
  1139.         for(sub=1;sub<MAX_MODELS;sub++)
  1140.         {
  1141.             Com_sprintf(temp, MAX_QPATH, "*%d-%d", i, sub);
  1142.             cgs.inlineDrawModel[breakPoint] = trap_R_RegisterModel( temp );
  1143.             if (!cgs.inlineDrawModel[breakPoint])
  1144.             {
  1145.                 break;
  1146.             }
  1147.             trap_R_ModelBounds( cgs.inlineDrawModel[breakPoint], mins, maxs );
  1148.             for ( j = 0 ; j < 3 ; j++ ) 
  1149.             {
  1150.                 cgs.inlineModelMidpoints[breakPoint][j] = mins[j] + 0.5 * ( maxs[j] - mins[j] );
  1151.             }
  1152.             breakPoint++;
  1153.         }
  1154.     }
  1155.  
  1156. //    cg.mInRMG = qfalse;
  1157.  
  1158.     // Register  all the terrain ents
  1159.     CG_LoadingString( "Creating terrain" );
  1160.     for(i = 1; i < MAX_TERRAINS; i++)
  1161.     {
  1162.         terrainInfo = CG_ConfigString( CS_TERRAINS + i );
  1163.         if ( !terrainInfo[0] )
  1164.         {
  1165.             break;
  1166.         }
  1167.  
  1168.         terrainID = trap_CM_RegisterTerrain(terrainInfo);
  1169. /*
  1170.         if (i == 1)
  1171.         {
  1172.             cg.mInRMG = qtrue;
  1173.         }
  1174. */
  1175.  
  1176.         trap_RMG_Init(terrainID, terrainInfo);
  1177.  
  1178.         // Send off the terrainInfo to the renderer
  1179.         trap_RE_InitRendererTerrain( terrainInfo );
  1180.     }
  1181.  
  1182.     if (cg.mInRMG)
  1183.     {
  1184.         const char* info;
  1185.  
  1186.         trap_CM_TM_Upload(0, 0);        // do not draw the origin / angles on the map itself
  1187.         cgs.media.mAutomap = trap_R_RegisterShader( "gfx/menus/rmg/automap" );
  1188.  
  1189.         cgs.mIRDist = RMG_distancecull.integer;
  1190.  
  1191.         info = CG_ConfigString ( CS_SYSTEMINFO );
  1192.         trap_Cvar_Set ( "ui_about_seed", Info_ValueForKey ( info,"RMG_textseed" ) );
  1193.     }
  1194.     else
  1195.     {
  1196.         trap_R_ModelBounds( cgs.inlineDrawModel[0], cgs.mWorldMins, cgs.mWorldMaxs );
  1197.         VectorSubtract(cgs.mWorldMaxs, cgs.mWorldMins, distance);
  1198.         cgs.mIRDist = VectorLength(distance);
  1199. //        cgs.mIRSeeThrough = cgs.mIRDist / 2.0;
  1200.     }
  1201.     cgs.mIRDist = 2500.0;
  1202.     cgs.mIRSeeThrough = 150.0;
  1203.  
  1204.     CG_LoadingString("skins");
  1205.  
  1206.     cgs.media.damageDirShader = trap_R_RegisterShader("gfx/misc/hit_direction_final");
  1207.     cgs.media.glassChunkEffect = trap_FX_RegisterEffect ( "chunks/debris_glass.efx" );
  1208.  
  1209.     cgs.media.playerFleshImpactEffect = trap_FX_RegisterEffect ( "blood_squirt_mp.efx" );
  1210.     cgs.media.mBloodSmall = trap_FX_RegisterEffect ( "impact_player_mp.efx" );
  1211.  
  1212.     cgs.media.test = trap_FX_RegisterEffect ( "arterial_squirt_small.efx" );
  1213.  
  1214.     trap_G2API_InitGhoul2Model ( &cgs.media.nightVisionModel, "models/characters/bolt_ons/nightvision_bolt_on.glm", 0, 0, 0, 0, 0 );
  1215.  
  1216.     CG_LoadingStage ( 13 );
  1217. }
  1218.  
  1219. /*                                                                                                                                            
  1220. ===================
  1221. CG_RegisterClients
  1222. ===================
  1223. */
  1224. static void CG_RegisterClients( void ) 
  1225. {
  1226.     int        i;
  1227.  
  1228.     CG_LoadingClient(cg.clientNum);
  1229.     CG_NewClientInfo(cg.clientNum);
  1230.  
  1231.     for (i=0 ; i<MAX_CLIENTS ; i++) 
  1232.     {
  1233.         const char        *clientInfo;
  1234.  
  1235.         if (cg.clientNum == i) 
  1236.         {
  1237.             continue;
  1238.         }
  1239.  
  1240.         clientInfo = CG_ConfigString( CS_PLAYERS+i );
  1241.         
  1242.         if ( !clientInfo[0]) 
  1243.         {
  1244.             continue;
  1245.         }
  1246.         
  1247.         CG_LoadingClient( i );
  1248.         CG_NewClientInfo( i );
  1249.     }
  1250. }
  1251.  
  1252. //===========================================================================
  1253.  
  1254. /*
  1255. =================
  1256. CG_ConfigString
  1257. =================
  1258. */
  1259. const char *CG_ConfigString( int index ) 
  1260. {
  1261.     if ( index < 0 || index >= MAX_CONFIGSTRINGS ) 
  1262.     {
  1263.         Com_Error( ERR_FATAL, "CG_ConfigString: bad index: %i", index );
  1264.     }
  1265.  
  1266.     return cgs.gameState.stringData + cgs.gameState.stringOffsets[ index ];
  1267. }
  1268.  
  1269. //==================================================================
  1270.  
  1271. /*
  1272. ======================
  1273. CG_StartMusic
  1274.  
  1275. ======================
  1276. */
  1277. void CG_StartMusic( qboolean bForceStart ) 
  1278. {
  1279.     const char    *s;
  1280.     char        parm1[MAX_QPATH], parm2[MAX_QPATH];
  1281.  
  1282.     // start the background music
  1283.     s = (char *)CG_ConfigString( CS_MUSIC );
  1284.     Q_strncpyz( parm1, COM_Parse( &s ), sizeof( parm1 ) );
  1285.     Q_strncpyz( parm2, COM_Parse( &s ), sizeof( parm2 ) );
  1286.  
  1287.     if (!parm2[0])
  1288.     {
  1289.         strcpy(parm2, parm1);
  1290.     }
  1291.     if ( *parm1 && *parm2 )
  1292.     {
  1293.         trap_S_StartBackgroundTrack( parm1, parm2, !bForceStart );
  1294.     }
  1295. }
  1296.  
  1297. char *CG_GetMenuBuffer(const char *filename) 
  1298. {
  1299.     int    len;
  1300.     fileHandle_t    f;
  1301.     static char buf[MAX_MENUFILE];
  1302.  
  1303.     len = trap_FS_FOpenFile( filename, &f, FS_READ );
  1304.     if ( !f ) {
  1305.         trap_Print( va( S_COLOR_RED "menu file not found: %s, using default\n", filename ) );
  1306.         return NULL;
  1307.     }
  1308.     if ( len >= MAX_MENUFILE ) {
  1309.         trap_Print( va( S_COLOR_RED "menu file too large: %s is %i, max allowed is %i", filename, len, MAX_MENUFILE ) );
  1310.         trap_FS_FCloseFile( f );
  1311.         return NULL;
  1312.     }
  1313.  
  1314.     trap_FS_Read( buf, len, f );
  1315.     buf[len] = 0;
  1316.     trap_FS_FCloseFile( f );
  1317.  
  1318.     return buf;
  1319. }
  1320.  
  1321. //
  1322. // ==============================
  1323. // new hud stuff ( mission pack )
  1324. // ==============================
  1325. //
  1326. qboolean CG_Asset_Parse(int handle) {
  1327.     pc_token_t token;
  1328.     const char *tempStr;
  1329.  
  1330.     if (!trap_PC_ReadToken(handle, &token))
  1331.         return qfalse;
  1332.     if (Q_stricmp(token.string, "{") != 0) {
  1333.         return qfalse;
  1334.     }
  1335.     
  1336.     while ( 1 ) 
  1337.     {
  1338.         if (!trap_PC_ReadToken(handle, &token))
  1339.             return qfalse;
  1340.  
  1341.         if (Q_stricmp(token.string, "}") == 0) 
  1342.         {
  1343.             return qtrue;
  1344.         }
  1345.  
  1346.         // font
  1347.         if (Q_stricmp(token.string, "defaultFont") == 0) 
  1348.         {
  1349.             if (!PC_String_Parse(handle, &tempStr) ) 
  1350.             {
  1351.                 return qfalse;
  1352.             }
  1353.             cgDC.Assets.defaultFont = cgDC.registerFont(tempStr);
  1354.             continue;
  1355.         }
  1356.  
  1357.         // itemFocusSound
  1358.         if (Q_stricmp(token.string, "itemFocusSound") == 0) 
  1359.         {
  1360.             if (!PC_String_Parse(handle, &tempStr)) 
  1361.             {
  1362.                 return qfalse;
  1363.             }
  1364.             cgDC.Assets.itemFocusSound = trap_S_RegisterSound( tempStr );
  1365.             continue;
  1366.         }
  1367.  
  1368.         if (Q_stricmp(token.string, "cursor") == 0) {
  1369.             if (!PC_String_Parse(handle, &cgDC.Assets.cursorStr)) {
  1370.                 return qfalse;
  1371.             }
  1372.             cgDC.Assets.cursor = trap_R_RegisterShaderNoMip( cgDC.Assets.cursorStr);
  1373.             continue;
  1374.         }
  1375.  
  1376.         if (Q_stricmp(token.string, "fadeClamp") == 0) {
  1377.             if (!PC_Float_Parse(handle, &cgDC.Assets.fadeClamp)) {
  1378.                 return qfalse;
  1379.             }
  1380.             continue;
  1381.         }
  1382.  
  1383.         if (Q_stricmp(token.string, "fadeCycle") == 0) {
  1384.             if (!PC_Int_Parse(handle, &cgDC.Assets.fadeCycle)) {
  1385.                 return qfalse;
  1386.             }
  1387.             continue;
  1388.         }
  1389.  
  1390.         if (Q_stricmp(token.string, "fadeAmount") == 0) {
  1391.             if (!PC_Float_Parse(handle, &cgDC.Assets.fadeAmount)) {
  1392.                 return qfalse;
  1393.             }
  1394.             continue;
  1395.         }
  1396.  
  1397.         if (Q_stricmp(token.string, "shadowX") == 0) {
  1398.             if (!PC_Float_Parse(handle, &cgDC.Assets.shadowX)) {
  1399.                 return qfalse;
  1400.             }
  1401.             continue;
  1402.         }
  1403.  
  1404.         if (Q_stricmp(token.string, "shadowY") == 0) {
  1405.             if (!PC_Float_Parse(handle, &cgDC.Assets.shadowY)) {
  1406.                 return qfalse;
  1407.             }
  1408.             continue;
  1409.         }
  1410.  
  1411.         if (Q_stricmp(token.string, "shader") == 0) 
  1412.         {
  1413.             if (!PC_String_Parse(handle, &tempStr)) 
  1414.             {
  1415.                 return qfalse;
  1416.             }
  1417.             trap_R_RegisterShaderNoMip ( tempStr );
  1418.             continue;
  1419.         }
  1420.  
  1421.         if (Q_stricmp(token.string, "shadowColor") == 0) {
  1422.             if (!PC_Color_Parse(handle, &cgDC.Assets.shadowColor)) {
  1423.                 return qfalse;
  1424.             }
  1425.             cgDC.Assets.shadowFadeClamp = cgDC.Assets.shadowColor[3];
  1426.             continue;
  1427.         }
  1428.     }
  1429.     return qfalse; // bk001204 - why not?
  1430. }
  1431.  
  1432. /*
  1433. ======================
  1434. CG_ParseMenu
  1435. ======================
  1436. */
  1437. void CG_ParseMenu ( const char *menuFile )
  1438. {
  1439.     pc_token_t    token;
  1440.     int            handle;
  1441.  
  1442.     // Load the menu file
  1443.     handle = trap_PC_LoadSource(menuFile);
  1444.     if (!handle)
  1445.     {
  1446.         return;
  1447.     }
  1448.  
  1449.     while ( 1 ) 
  1450.     {
  1451.         if (!trap_PC_ReadToken( handle, &token )) 
  1452.         {
  1453.             break;
  1454.         }
  1455.  
  1456.         if ( token.string[0] == '}' ) 
  1457.         {
  1458.             break;
  1459.         }
  1460.  
  1461.         if (Q_stricmp(token.string, "assetGlobalDef") == 0) 
  1462.         {
  1463.             if (CG_Asset_Parse(handle)) 
  1464.             {
  1465.                 continue;
  1466.             } 
  1467.             else 
  1468.             {
  1469.                 break;
  1470.             }
  1471.         }
  1472.  
  1473.         if (Q_stricmp(token.string, "menudef") == 0) 
  1474.         {
  1475.             // start a new menu
  1476.             Menu_New ( handle );
  1477.         }
  1478.     }
  1479.  
  1480.     trap_PC_FreeSource(handle);
  1481. }
  1482.  
  1483. /*
  1484. ======================
  1485. CG_LoadMenu
  1486. ======================
  1487. */
  1488. qboolean CG_LoadMenu ( const char **p ) 
  1489. {
  1490.     char *token;
  1491.  
  1492.     token = COM_ParseExt(p, qtrue);
  1493.  
  1494.     if (token[0] != '{') 
  1495.     {
  1496.         return qfalse;
  1497.     }
  1498.  
  1499.     while ( 1 ) 
  1500.     {
  1501.         token = COM_ParseExt(p, qtrue);
  1502.     
  1503.         if (Q_stricmp(token, "}") == 0) 
  1504.         {
  1505.             return qtrue;
  1506.         }
  1507.  
  1508.         if ( !token || token[0] == 0 ) 
  1509.         {
  1510.             return qfalse;
  1511.         }
  1512.  
  1513.         CG_ParseMenu(token); 
  1514.     }
  1515.  
  1516.     return qfalse;
  1517. }
  1518.  
  1519. /*
  1520. ======================
  1521. CG_LoadMenus
  1522. ======================
  1523. */
  1524. void CG_LoadMenus ( const char *menuFile ) 
  1525. {
  1526.     char            *token;
  1527.     const char        *p;
  1528.     int                len, start;
  1529.     fileHandle_t    f;
  1530.     static char        buf[MAX_MENUDEFFILE];
  1531.  
  1532.     start = trap_Milliseconds();
  1533.  
  1534.     trap_PC_LoadGlobalDefines ( "ui/menudef.h" );
  1535.  
  1536.     // Open the hud menu file
  1537.     len = trap_FS_FOpenFile( menuFile, &f, FS_READ );
  1538.     if ( !f ) 
  1539.     {
  1540.         Com_Error( ERR_FATAL, va( S_COLOR_RED "hud menu file not found: ui/hud.txt, unable to continue!\n", menuFile ) );
  1541.         return;
  1542.     }
  1543.  
  1544.     // Too big?
  1545.     if ( len >= MAX_MENUDEFFILE ) 
  1546.     {
  1547.         Com_Error( ERR_FATAL, va( S_COLOR_RED "menu file too large: %s is %i, max allowed is %i", menuFile, len, MAX_MENUDEFFILE ) );
  1548.         trap_FS_FCloseFile( f );
  1549.         return;
  1550.     }
  1551.  
  1552.     trap_FS_Read( buf, len, f );
  1553.     buf[len] = 0;
  1554.     trap_FS_FCloseFile( f );
  1555.     
  1556.     COM_Compress(buf);
  1557.  
  1558.     Menu_Reset();
  1559.  
  1560.     p = buf;
  1561.  
  1562.     while ( 1 ) 
  1563.     {
  1564.         token = COM_ParseExt( &p, qtrue );
  1565.         if( !token || token[0] == 0 || token[0] == '}') 
  1566.         {
  1567.             break;
  1568.         }
  1569.  
  1570.         if ( Q_stricmp( token, "}" ) == 0 ) 
  1571.         {
  1572.             break;
  1573.         }
  1574.  
  1575.         if (Q_stricmp(token, "loadmenu") == 0) 
  1576.         {
  1577.             if ( CG_LoadMenu ( &p ) ) 
  1578.             {
  1579.                 continue;
  1580.             } 
  1581.             else 
  1582.             {
  1583.                 break;
  1584.             }
  1585.         }
  1586.     }
  1587.  
  1588.     trap_PC_RemoveAllGlobalDefines ( );
  1589.  
  1590.     Com_Printf("HUD menu load time = %d milli seconds\n", trap_Milliseconds() - start);
  1591. }
  1592.  
  1593. /*
  1594. ======================
  1595. CG_LoadMenus
  1596. ======================
  1597. */
  1598. static qboolean CG_OwnerDrawHandleKey(int ownerDraw, int flags, float *special, int key, const char* param ) 
  1599. {
  1600.     return qfalse;
  1601. }
  1602.  
  1603.  
  1604. static int CG_FeederCount(float feederID) 
  1605. {
  1606.     return 0;
  1607. }
  1608.  
  1609. static const char *CG_FeederItemText ( float feederID, int index, int column, qhandle_t *handle) 
  1610. {
  1611.     return "";
  1612. }
  1613.  
  1614. static qhandle_t CG_FeederItemImage(float feederID, int index) 
  1615. {
  1616.     return 0;
  1617. }
  1618.  
  1619. static void CG_FeederSelection(float feederID, int index) 
  1620. {
  1621. }
  1622.  
  1623. static float CG_Cvar_Get(const char *cvar) 
  1624. {
  1625.     char buff[128];
  1626.     memset(buff, 0, sizeof(buff));
  1627.     trap_Cvar_VariableStringBuffer(cvar, buff, sizeof(buff));
  1628.  
  1629.     return atof(buff);
  1630. }
  1631.  
  1632. static int CG_OwnerDrawWidth(int ownerDraw, qhandle_t font, float scale ) 
  1633. {
  1634.     switch (ownerDraw) 
  1635.     {
  1636.         case CG_GAME_TYPE:
  1637.             return trap_R_GetTextWidth (CG_GameTypeString(), font, scale, 0 );
  1638.  
  1639.         case CG_GAME_STATUS:
  1640.             return trap_R_GetTextWidth (CG_GetGameStatusText(), font, scale, 0 );
  1641.     }
  1642.  
  1643.     return 0;
  1644. }
  1645.  
  1646. static int CG_PlayCinematic(const char *name, float x, float y, float w, float h) {
  1647.   return trap_CIN_PlayCinematic(name, x, y, w, h, CIN_loop);
  1648. }
  1649.  
  1650. static void CG_StopCinematic(int handle) {
  1651.   trap_CIN_StopCinematic(handle);
  1652. }
  1653.  
  1654. static void CG_DrawCinematic(int handle, float x, float y, float w, float h) {
  1655.   trap_CIN_SetExtents(handle, x, y, w, h);
  1656.   trap_CIN_DrawCinematic(handle);
  1657. }
  1658.  
  1659. static void CG_RunCinematicFrame(int handle) {
  1660.   trap_CIN_RunCinematic(handle);
  1661. }
  1662.  
  1663. /*
  1664. =================
  1665. CG_LoadHudMenu
  1666. =================
  1667. */
  1668. void CG_LoadHudMenu() 
  1669. {
  1670.     cgDC.registerShaderNoMip    = &trap_R_RegisterShaderNoMip;
  1671.     cgDC.setColor                = &trap_R_SetColor;
  1672.     cgDC.drawHandlePic            = &CG_DrawPic;
  1673.     cgDC.drawStretchPic            = &trap_R_DrawStretchPic;
  1674.     cgDC.drawText                = &CG_DrawText;
  1675.     cgDC.drawTextWithCursor        = &CG_DrawTextWithCursor;
  1676.     cgDC.getTextWidth            = &trap_R_GetTextWidth;
  1677.     cgDC.getTextHeight            = &trap_R_GetTextHeight;
  1678.     cgDC.registerModel            = &trap_R_RegisterModel;
  1679.     cgDC.modelBounds            = &trap_R_ModelBounds;
  1680.     cgDC.fillRect                = &CG_FillRect;
  1681.     cgDC.drawRect                = &CG_DrawRect;   
  1682.     cgDC.drawSides                = &CG_DrawSides;
  1683.     cgDC.drawTopBottom            = &CG_DrawTopBottom;
  1684.     cgDC.clearScene                = &trap_R_ClearScene;
  1685.     cgDC.addRefEntityToScene    = &trap_R_AddRefEntityToScene;
  1686.     cgDC.renderScene            = &trap_R_RenderScene;
  1687.     cgDC.registerFont            = &trap_R_RegisterFont;
  1688.     cgDC.ownerDrawItem            = &CG_OwnerDraw;
  1689.     cgDC.getValue                = &CG_GetValue;
  1690.     cgDC.ownerDrawVisible        = &CG_OwnerDrawVisible;
  1691.     cgDC.ownerDrawDisabled        = &CG_OwnerDrawDisabled;
  1692.     cgDC.runScript                = &CG_RunMenuScript;
  1693.     cgDC.getTeamColor            = &CG_GetTeamColor;
  1694.     cgDC.setCVar                = trap_Cvar_Set;
  1695.     cgDC.getCVarString            = trap_Cvar_VariableStringBuffer;
  1696.     cgDC.getCVarValue            = CG_Cvar_Get;
  1697.     cgDC.startLocalSound        = &trap_S_StartLocalSound;
  1698.     cgDC.ownerDrawHandleKey        = &CG_OwnerDrawHandleKey;
  1699.     cgDC.feederCount            = &CG_FeederCount;
  1700.     cgDC.feederItemImage        = &CG_FeederItemImage;
  1701.     cgDC.feederItemText            = &CG_FeederItemText;
  1702.     cgDC.feederSelection        = &CG_FeederSelection;
  1703.     cgDC.Error                    = &Com_Error; 
  1704.     cgDC.Print                    = &Com_Printf; 
  1705.     cgDC.ownerDrawWidth            = &CG_OwnerDrawWidth;
  1706.     cgDC.registerSound            = &trap_S_RegisterSound;
  1707.     cgDC.startBackgroundTrack    = &trap_S_StartBackgroundTrack;
  1708.     cgDC.stopBackgroundTrack    = &trap_S_StopBackgroundTrack;
  1709.     cgDC.playCinematic            = &CG_PlayCinematic;
  1710.     cgDC.stopCinematic            = &CG_StopCinematic;
  1711.     cgDC.drawCinematic =         &CG_DrawCinematic;
  1712.     cgDC.runCinematicFrame        = &CG_RunCinematicFrame;
  1713.  
  1714.     cgDC.yscale = cgDC.glconfig.vidHeight * (1.0/480.0);
  1715.     cgDC.xscale = cgDC.glconfig.vidWidth * (1.0/640.0);
  1716.  
  1717.     Init_Display(&cgDC);
  1718.  
  1719.     Menu_Reset();
  1720.  
  1721.     CG_LoadMenus( "ui/hud.txt" );
  1722. }
  1723.  
  1724. /*
  1725. =================
  1726. CG_AssetCache
  1727. =================
  1728. */
  1729. void CG_AssetCache() 
  1730. {
  1731.     cgDC.Assets.scrollBar            = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR );
  1732.     cgDC.Assets.scrollBarArrowDown    = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWDOWN );
  1733.     cgDC.Assets.scrollBarArrowUp    = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWUP );
  1734.     cgDC.Assets.scrollBarArrowLeft    = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWLEFT );
  1735.     cgDC.Assets.scrollBarArrowRight = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWRIGHT );
  1736.     cgDC.Assets.scrollBarThumb        = trap_R_RegisterShaderNoMip( ASSET_SCROLL_THUMB );
  1737.     cgDC.Assets.sliderBar            = trap_R_RegisterShaderNoMip( ASSET_SLIDER_BAR );
  1738.     cgDC.Assets.sliderThumb            = trap_R_RegisterShaderNoMip( ASSET_SLIDER_THUMB );
  1739. }
  1740.  
  1741. // initialise the cg_entities structure - take into account the ghoul2 stl stuff in the active snap shots
  1742. void CG_Init_CG(void)
  1743. {
  1744.     memset( &cg, 0, sizeof(cg));
  1745. }
  1746.  
  1747. // initialise the cg_entities structure - take into account the ghoul2 stl stuff
  1748. void CG_Init_CGents(void)
  1749. {
  1750.     memset(&cg_entities, 0, sizeof(cg_entities));
  1751. }
  1752.  
  1753. void CG_InitItems(void)
  1754. {
  1755.     memset( cg_items, 0, sizeof( cg_items ) );
  1756. }
  1757.  
  1758. void CG_TransitionPermanent(void)
  1759. {
  1760.     centity_t    *cent = cg_entities;
  1761.     int            i;
  1762.  
  1763.     cg_numpermanents = 0;
  1764.     for(i=0;i<MAX_GENTITIES;i++,cent++)
  1765.     {
  1766.         if (trap_GetDefaultState(i, ¢->currentState))
  1767.         {
  1768.             cent->nextState = cent->currentState;
  1769.             VectorCopy (cent->currentState.origin, cent->lerpOrigin);
  1770.             VectorCopy (cent->currentState.angles, cent->lerpAngles);
  1771.             cent->currentValid = qtrue;
  1772.  
  1773.             cg_permanents[cg_numpermanents++] = cent;
  1774.         }
  1775.     }
  1776. }
  1777.  
  1778. /*
  1779. =================
  1780. CG_Init
  1781.  
  1782. Called after every level change or subsystem restart
  1783. Will perform callbacks to make the loading info screen update.
  1784. =================
  1785. */
  1786. void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ) 
  1787. {
  1788.     const char    *s;
  1789.  
  1790.     // Some of the new SOF2 features required more traffic through 
  1791.     // the trap calls than than the original vm code would allow for.  Therefore
  1792.     // a block of shared memory is registered with the engine to allow for
  1793.     // larger pieced of data to be transferred back and forth.
  1794.     trap_CG_RegisterSharedMemory(cg.sharedBuffer);
  1795.  
  1796.     // clear everything
  1797.     CG_Init_CGents();
  1798.     CG_Init_CG();
  1799.     CG_InitItems();
  1800.  
  1801.     BG_ParseNPCFiles ( );
  1802.  
  1803.     memset( &cgs, 0, sizeof( cgs ) );
  1804.     memset( cg_weapons, 0, sizeof(cg_weapons) );
  1805.  
  1806.     // Load these first since they are used to display the status
  1807.     cgs.media.loadBulletShader    = trap_R_RegisterShaderNoMip ( "gfx/menus/misc/load_bullet.tga" );
  1808.     cgs.media.loadClipShader    = trap_R_RegisterShaderNoMip ( "gfx/menus/misc/load_clip.tga" );
  1809.     cgs.media.whiteShader        = trap_R_RegisterShaderNoMip ( "white" );
  1810.  
  1811.     cg.clientNum = clientNum;
  1812.  
  1813.     cgs.processedSnapshotNum = serverMessageNum;
  1814.     cgs.serverCommandSequence = serverCommandSequence;
  1815.  
  1816.     CG_LoadingStage ( 0 );
  1817.  
  1818.     CG_RegisterCvars();
  1819.  
  1820.     CG_InitConsoleCommands();
  1821.  
  1822.     // Populate the gametypeData array with the gametypes available
  1823.     // in the scripts directory
  1824.     BG_BuildGametypeList();
  1825.  
  1826.     cg.weaponSelect = WP_USSOCOM_PISTOL;
  1827.  
  1828.     // get the rendering configuration from the client system
  1829.     trap_GetGlconfig( &cgs.glconfig );
  1830.     cgs.screenXScale = cgs.glconfig.vidWidth / 640.0;
  1831.     cgs.screenYScale = cgs.glconfig.vidHeight / 480.0;
  1832.  
  1833.     // Register the fonts
  1834.     cgs.media.hudFont = trap_R_RegisterFont ( "hud" );
  1835.     cgs.media.lcdFont = trap_R_RegisterFont ( "lcdsmall" );
  1836.  
  1837.     // Load the user interface
  1838.     String_Init();
  1839.     CG_AssetCache();
  1840.     CG_LoadHudMenu();
  1841.  
  1842.     // get the gamestate from the client system
  1843.     trap_GetGameState( &cgs.gameState );
  1844.  
  1845.     CG_TransitionPermanent();
  1846.  
  1847.     // check version
  1848.     s = CG_ConfigString( CS_GAME_VERSION );
  1849.     if ( strcmp( s, GAME_VERSION ) ) 
  1850.     {
  1851.         Com_Error( ERR_FATAL, "Client/Server game mismatch: %s/%s", GAME_VERSION, s );
  1852.     }
  1853.  
  1854.     s = CG_ConfigString( CS_LEVEL_START_TIME );
  1855.     cgs.levelStartTime = atoi( s );
  1856.     
  1857.     CG_ParseServerinfo();
  1858.  
  1859.     CG_ParseGametypeFile ( );
  1860.  
  1861.     // load the new map
  1862.     CG_LoadingString( "collision map" );
  1863.  
  1864.     CG_LoadingStage ( 1 );
  1865.  
  1866.     trap_CM_LoadMap( cgs.mapname, qfalse );
  1867.  
  1868.     // Make sure we have update values (scores)
  1869.     CG_SetConfigValues();
  1870.  
  1871.     CG_LoadingStage ( 2 );
  1872.  
  1873.     // force players to load instead of defer
  1874.     cg.loading = qtrue;        
  1875.  
  1876.     CG_LoadingString( "sounds" );
  1877.  
  1878.     CG_RegisterLadders ( );
  1879.     CG_RegisterSounds();
  1880.     CG_InitHitModel( );
  1881.  
  1882.     CG_LoadingString( "graphics" );
  1883.     BG_ParseInviewFile ( cgs.pickupsDisabled );
  1884.     CG_RegisterGraphics ( );
  1885.  
  1886. //    CG_RegisterMission ( );
  1887.  
  1888.     CG_ParseGore();
  1889.  
  1890.     CG_LoadingString( "clients" );
  1891.  
  1892.     CG_RegisterClients();        // if low on memory, some clients will be deferred
  1893.  
  1894.     CG_LoadingStage ( 14 );
  1895.  
  1896.     CG_InitLocalEntities();
  1897.  
  1898.     CG_LoadingStage ( 15 );
  1899.  
  1900.     CG_StartMusic(qfalse);
  1901.  
  1902.     CG_LoadingString( "Clearing light styles" );
  1903.     CG_ClearLightStyles();
  1904.  
  1905.     CG_LoadingString( "" );
  1906.  
  1907.     CG_ShaderStateChanged();
  1908.  
  1909.     trap_S_ClearLoopingSounds( qtrue );
  1910.  
  1911.     // In a mission game we want to bring up the objective screen on initial connection
  1912.     if ( cgs.gametypeData->description || cgs.pickupsDisabled || cgs.gametypeData->teams  )
  1913.     {
  1914.         cg.popupObjectives = qtrue;
  1915.     }
  1916.  
  1917.     trap_Cvar_Set ( "ui_info_gametype", va("%i",cgs.gametype ) );
  1918.     trap_Cvar_Set ( "ui_info_objectives", cgs.gametypeData->description );
  1919.     trap_Cvar_Set ( "con_draw", cg.scoreBoardShowing?"0":"1" );
  1920.  
  1921.     // remove the last loading update
  1922.     cg.infoScreenText[0] = 0;
  1923.  
  1924.     cg.loading = qfalse;    // future players will be deferred
  1925. }
  1926.  
  1927. void CG_ShutdownG2Models(void)
  1928. {
  1929.     int                i, j;
  1930.     clientInfo_t    *ci;
  1931.  
  1932.     for(i=0;i<MAX_ITEMS;i++)
  1933.     {
  1934.         for(j=0;j<MAX_ITEM_MODELS;j++)
  1935.         {
  1936.             if (cg_items[i].g2Models[j])
  1937.             {
  1938.                 trap_G2API_CleanGhoul2Models(&cg_items[i].g2Models[j]);
  1939.             }
  1940.         }
  1941.     }
  1942.  
  1943.     for(i=0;i<MAX_GENTITIES;i++)
  1944.     {
  1945.         if (cg_entities[i].ghoul2)
  1946.         {
  1947.             trap_G2API_CleanGhoul2Models(&cg_entities[i].ghoul2);
  1948.         }
  1949.     }
  1950.  
  1951.     for(i=0;i<MAX_CLIENTS;i++)
  1952.     {
  1953.         ci = &cgs.clientinfo[i];
  1954.         if (ci->ghoul2Model)
  1955.         {
  1956.             trap_G2API_CleanGhoul2Models(&ci->ghoul2Model);
  1957.         }
  1958.     }
  1959. }
  1960.  
  1961. void CG_ShutdownGore(void);
  1962.  
  1963. /*
  1964. =================
  1965. CG_Shutdown
  1966.  
  1967. Called before every level change or subsystem restart
  1968. =================
  1969. */
  1970. void CG_Shutdown( void ) 
  1971. {
  1972.     trap_FX_FreeSystem();
  1973.  
  1974.     CG_ShutDownWeapons();
  1975.     CG_ShutdownG2Models();
  1976.  
  1977.     CG_ShutdownGore();
  1978.  
  1979.     // some mods may need to do cleanup work here,
  1980.     // like closing files or archiving session data
  1981. }
  1982.